package dmxGroupControl.ui;

import dmxGroupControl.DMXFixture;
import dmxGroupControl.Group;
import dmxGroupControl.LightController;
import dmxGroupControl.Pixel;
import dmxGroupControl.PixelFixture;
import dmxGroupControl.Universe;
import dmxGroupControl.listeners.Listener;
import dmxGroupControl.transmitters.Transmitter;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.layout.*;

public class fxWindow extends Application {
	
	private static final int PIXEL_SIZE = 8;
	private static final int PIXEL_SPACING = 24;
	
	String venueFile;
	
	public fxWindow(String venueFile)
	{
	    this.venueFile = venueFile;
	}
	
	@Override
	public void start(Stage primaryStage) {
		try {
		    Platform.setImplicitExit(true);
		    
		    LightController.Initialize(venueFile);
			
		    primaryStage.setOnCloseRequest((event) -> LightController.GetInstance().close());
		    
			Parent layoutRoot = SetupScene();
			Scene scene = new Scene(layoutRoot);
			scene.getStylesheets().add(getClass().getResource("/resources/mainWindow.css").toExternalForm());
			primaryStage.setTitle(LightController.GetInstance().GetUniverses().get(0).GetName());
			primaryStage.setScene(scene);
			
			primaryStage.show();
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
		
	@Override
	public void stop()
	{
	    Platform.exit();
	}
	
	private Parent SetupScene()
	{
	    TabPane universes = new TabPane();
	    universes.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
	    universes.getStyleClass().add("universes");

	    Insets pixelMargin = new Insets(PIXEL_SPACING / 2);

        //create the universes
	    for(Universe universe : LightController.GetInstance().GetUniverses())
	    {
	        Tab universeTab = new Tab(universe.toString());
	        universes.getTabs().add(universeTab);

            ScrollPane scrollPane = new ScrollPane();
            universeTab.setContent(scrollPane);

            FlowPane groups = new FlowPane();
	        groups.getStyleClass().add("groups");
	        scrollPane.setContent(groups);
	        //universeTab.setContent(groups);

	        for(Group group : universe.GetGroups())
	        {
	            VBox groupBox = new VBox();
	            groupBox.getStyleClass().add("groupBox");

	            Text groupTitleText = new Text(group.GetName());
	            groupBox.getChildren().add(groupTitleText);

	            HBox fixtures = new HBox();

	            for(DMXFixture fixture : group.GetDMXFixtures())
	            {
	                VBox fixtureBox = new VBox();
	                fixtureBox.getStyleClass().add("fixtureBox");

	                Rectangle fixtureRect = new Rectangle();
	                fixtureRect.getStyleClass().add("fixtureRect");
	                fixtureRect.setWidth(64);
	                fixtureRect.setHeight(64);
	                fixture.SetRect(fixtureRect);

	                fixtureBox.setAlignment(Pos.CENTER);

	                StackPane stack = new StackPane();
	                stack.getStyleClass().add("displayStack");

	                fixtureBox.getChildren().add(stack);

	                stack.getChildren().add(fixtureRect);

	                if(fixture.IsPanning())
	                {
	                    Line line = new Line();
	                    line.setStartY(fixtureRect.getY());
	                    line.setEndY(fixtureRect.getY() + fixtureRect.getHeight());
	                    line.setStroke(Color.RED);
	                    fixture.SetPanLine(line);
	                    stack.getChildren().add(line);
	                }
	                if(fixture.IsTilting())
	                {
	                    Line line = new Line();
                        line.setStartX(fixtureRect.getX());
                        line.setEndX(fixtureRect.getX() + fixtureRect.getWidth());
                        fixture.SetTiltLine(line);
                        stack.getChildren().add(line);
	                }

	                Label fixtureDebugText = new Label();
	                fixture.SetDebugLabel(fixtureDebugText);

	                Label fixtureLabel = new Label(fixture.GetName());
	                Label fixtureDMXChannels = new Label(fixture.GetChannelStart() + " - " + fixture.GetChannelEnd());

	                fixtureBox.getChildren().add(fixtureLabel);
	                fixtureBox.getChildren().add(fixtureDMXChannels);
	                fixtureBox.getChildren().add(fixtureDebugText);

	                fixtures.getChildren().add(fixtureBox);
	            }

	            for(PixelFixture fixture : group.GetPixelFixtures())
	            {
	            	VBox fixtureBox = new VBox();
	                fixtureBox.getStyleClass().add("fixtureBox");

	                VBox rows = new VBox();
	                rows.getStyleClass().add("pixelBox");

	                int xPixels = fixture.GetXDimensions();
	                int yPixels = fixture.GetYDimensions();

	                for(int y = 0; y < yPixels; y++)
	        		{
	        			HBox row = new HBox();
	        			rows.getChildren().add(row);
	        			for(int x = 0; x < xPixels; x++)
	        			{
	        				Rectangle rectangle = new Rectangle(PIXEL_SIZE, PIXEL_SIZE);
	        				rectangle.getStyleClass().add("pixel");
	        				row.getChildren().add(rectangle);
	        				rectangle.setFill(Color.AZURE);
	        				HBox.setMargin(rectangle, pixelMargin);

	        				Pixel pixel = fixture.Get(x, y);
	        				pixel.SetRectangle(rectangle);
	        			}
	        		}

	                Label fixtureLabel = new Label(fixture.GetName());

	                fixtureBox.getChildren().add(rows);
	                fixtureBox.getChildren().add(fixtureLabel);
	                fixtures.getChildren().add(fixtureBox);
	            }

	            groupBox.getChildren().add(fixtures);
	            groups.getChildren().add(groupBox);
	        }
	    }

        //create the status pane
        Tab status = new Tab("Status");
        GridPane grid = new GridPane();
        grid.getStyleClass().add("statusGrid");
        status.setContent(grid);
        int row = 0;
        Insets gridMargin = new Insets(4, 8, 4, 8);
        Insets transmitterMargin = new Insets(4, 8, 4, 16);
        for(Listener listener : LightController.GetInstance().GetListeners())
        {
            Label name = new Label(listener.toString());
            name.getStyleClass().add("statusLabelName");
            Rectangle statusRect = new Rectangle(32, 32);
            statusRect.getStyleClass().add("statusRect");
            Label itemStatus = new Label("Not started");
            itemStatus.getStyleClass().add("statusLabel");

            listener.SetStatusLabel(itemStatus);
            listener.SetStatusRect(statusRect);

            grid.add(name, 0, row);
            grid.add(statusRect, 1, row);
            grid.add(itemStatus, 2, row);

            name.getStyleClass().add("statusLabelName");
            itemStatus.getStyleClass().add("statusLabel");
            statusRect.getStyleClass().add("statusRect");

            GridPane.setMargin(name, gridMargin);
            GridPane.setMargin(statusRect, gridMargin);
            GridPane.setMargin(itemStatus, gridMargin);
            row++;
        }

        for(Universe universe : LightController.GetInstance().GetUniverses())
        {
            Label universeName = new Label(universe.toString());
            grid.add(universeName, 0, row);
            universeName.getStyleClass().add("statusUniverseLabel");
            GridPane.setMargin(universeName, gridMargin);
            row++;

            for (Transmitter transmitter : universe.GetTransmitters())
            {
                Label name = new Label(transmitter.toString());
                Rectangle statusRect = new Rectangle(32, 32);
                Label itemStatus = new Label("Not started");

                transmitter.SetStatusLabel(itemStatus);
                transmitter.SetStatusRect(statusRect);

                grid.add(name, 0, row);
                grid.add(statusRect, 1, row);
                grid.add(itemStatus, 2, row);

                name.getStyleClass().add("statusLabelName");
                itemStatus.getStyleClass().add("statusLabel");
                statusRect.getStyleClass().add("statusRect");

                GridPane.setMargin(name, transmitterMargin);
                GridPane.setMargin(statusRect, gridMargin);
                GridPane.setMargin(itemStatus, gridMargin);

                row++;
            }
        }

        universes.getTabs().add(status);

	    return universes;
	}
}